package _04_queue.my_implements;

import _04_queue.AbstractQueue;

import java.util.ConcurrentModificationException;
import java.util.Iterator;

/**
 * @author: mornd
 * @dateTime: 2023/6/5 - 14:10
 * 环形数组实现2
 * 用 size 判断队列空满尾，头尾指针都存储元素
 */
public class ArrayQueue2<E> extends AbstractQueue<E> {
    Object[] data;

    // 头指针
    private int head = 0;
    // 尾指针
    private int tail = 0;

    private int capacity;

    int size;

    public ArrayQueue2(int capacity) {
        if (capacity < 0) {
            throw new IllegalArgumentException();
        }
        this.capacity = capacity;
        // 头尾指针都存储元素，都没闲着
        data = new Object[capacity];
    }

    @Override
    public boolean offer(E e) {
        if (isFull()) {
            return false;
        }
        data[tail] = e;
        tail = (tail + 1) % data.length;
        size++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        Object e = data[head];
        data[head] = null;
        head = (head + 1) % data.length;
        size--;
        return (E) e;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return (E) data[head];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isFull() {
        return size == capacity;
    }

    @Override
    public Iterator<E> iterator() {
        return new ArrayQueue2.Itr();
    }

    private class Itr implements Iterator<E> {
        int cursor = head;
        int lastRet = -1;
        int count;

        @Override
        public boolean hasNext() {
            return count < size;
        }

        @Override
        public E next() {
            Object e = data[lastRet = cursor];
            cursor = (cursor + 1) % data.length;
            count++;
            return (E) e;
        }

        @Override
        public void remove() {
            if (lastRet < 0)
                throw new IllegalStateException();
            try {
                ArrayQueue2.this.poll();
                lastRet = -1;
                count--;
            } catch (IndexOutOfBoundsException ex) {
                throw new ConcurrentModificationException();
            }
        }
    }
}
